package main

import (
	"bufio"
	"errors"
	"fmt"
	"io/fs"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

func ParseNginxConfig4Cert(configFilePath string) ([]IServer, error) {
	var servers []IServer
	configFilePath = JoinPathWithRoot(configFilePath)
	file, err := os.Open(configFilePath)
	if err != nil {
		if os.IsNotExist(err) {
			logger.Println("文件不存在: ", configFilePath)
			return servers, nil
		}
		return servers, fmt.Errorf("%s: %s", configFilePath, err)
	}
	defer file.Close()

	// 获取文件信息
	info, err := file.Stat()
	if err != nil {
		return servers, fmt.Errorf("获取文件信息错误：%v", err)
	}

	// 判断是文件还是目录
	if info.IsDir() {
		logger.Println("扫描目录: ", configFilePath)
		err = filepath.Walk(configFilePath, func(path string, info fs.FileInfo, err error) error {
			if err != nil || path == configFilePath {
				return err
			}
			serversInner, err := ParseNginxConfig4Cert(path)
			servers = append(servers, serversInner...)
			return nil
		})
		if err != nil {
			return servers, errors.New("遍历目录出错：" + err.Error())
		}
		return servers, nil
	}

	logger.Println("解析文件: ", configFilePath)

	var currentServer *Server
	scanner := bufio.NewScanner(file)
	includeRegex := regexp.MustCompile(`^\s*include\s+(.+);$`)
	serverRegex := regexp.MustCompile(`^\s*server\s+{`)
	nameRegex := regexp.MustCompile(`^\s*server_name\s+(.+?);$`)
	certKeyRegex := regexp.MustCompile(`^\s*ssl_certificate_key\s+(.+?);$`)
	certRegex := regexp.MustCompile(`^\s*ssl_certificate\s+(.+?);$`)

	for scanner.Scan() {
		line := scanner.Text()
		if includeRegex.MatchString(line) {
			if includeMatch := includeRegex.FindStringSubmatch(line); includeMatch != nil {
				pathInner := includeMatch[1]
				logger.Println("子配置文件: ", pathInner)
				idx := strings.Index(pathInner, "*")
				if idx > -1 {
					//logger.Printf("模糊查询: %s", pathInner)
					pathInner = pathInner[0:idx]
					idx = strings.LastIndex(pathInner, "/")
					if idx > -1 {
						pathInner = pathInner[:idx]
					}
				}
				serversInner, err := ParseNginxConfig4Cert(pathInner)
				if err != nil {
					return nil, err
				}
				servers = append(servers, serversInner...)
			}
		} else if serverRegex.MatchString(line) {
			currentServer = &Server{}
		} else if currentServer != nil {
			if nameMatch := nameRegex.FindStringSubmatch(line); nameMatch != nil {
				currentServer.Name = nameMatch[1]
			} else if keyMatch := certKeyRegex.FindStringSubmatch(line); keyMatch != nil {
				certKeyPath := replaceServerName(keyMatch[1], currentServer.Name)
				currentServer.CertificateKeyPath = certKeyPath
			} else if certMatch := certRegex.FindStringSubmatch(line); certMatch != nil {
				certPath := replaceServerName(certMatch[1], currentServer.Name)
				currentServer.CertificatePath = certPath
			} else if strings.TrimSpace(line) == "}" {
				if currentServer.CertificateKeyPath != "" {
					servers = append(servers, currentServer)
				}
				currentServer = nil // End of server block
			}
		}
	}
	return servers, scanner.Err()
}

func replaceServerName(path, serverName string) string {
	// Replace $server_name with the actual server name
	rs := strings.ReplaceAll(path, "${server_name}", serverName)
	rs = strings.ReplaceAll(rs, "$server_name", serverName)
	return rs
}
